using System.Collections;
using System.Collections.Generic;
using Main.Event;
using Main.NPC;
using UnityEngine;
using UnityEngine.Events;
using ZSW.Framework;

namespace Main.Dialogue
{
    [RequireComponent(typeof(NPCMovement))]
    [RequireComponent(typeof(BoxCollider2D))]
    public class DialogueController : ZSWF_InitMonoBehaviour
    {
        [Header("Component")]
        public NPCMovement npc;
        public GameObject TalkSign;
        [Header("Data")]
        public List<DialoguePiece> dialogueList = new List<DialoguePiece>();
        public Stack<DialoguePiece> dialogueStack;
        [Header("Event")]
        public UnityEvent OnFinishEvent;
        [Header("Condition")]
        public bool canTalk;
        public bool isTalking;

        public override void Init()
        {
            base.Init();

            FillDialogueStack();
        }

        private void Update()
        {
            TalkSign.SetActive(canTalk);

            if (canTalk && Input.GetKeyDown(KeyCode.Space) && !isTalking)
            {
                StartCoroutine(DialogueRoutine());
            }
        }

        private void OnTriggerEnter2D(Collider2D other)
        {
            if (other.CompareTag("Player"))
            {
                canTalk = !npc.isMoving && npc.interactable;
            }
        }

        private void OnTriggerExit2D(Collider2D other)
        {
            if (other.CompareTag("Player"))
            {
                canTalk = false;
            }
        }

        private void FillDialogueStack()
        {
            dialogueStack = new Stack<DialoguePiece>();
            for (int i = dialogueList.Count - 1; i >= 0; i--)
            {
                dialogueList[i].isDone = false;
                dialogueStack.Push(dialogueList[i]);
            }
        }


        // 对话携程
        private IEnumerator DialogueRoutine()
        {
            isTalking = true;

            if (dialogueStack.TryPop(out var result))
            {
                MainEventSystem.CallShowDialogueEvent(result);
                MainEventSystem.CallUpdateGameStateEvent(GameState.Pause);
                yield return new WaitUntil(() => result.isDone);
                isTalking = false;
            }
            else
            {
                MainEventSystem.CallShowDialogueEvent(null);

                MainEventSystem.CallUpdateGameStateEvent(GameState.GamePlay);

                FillDialogueStack();

                isTalking = false;

                if (OnFinishEvent != null)
                {
                    OnFinishEvent.Invoke();
                    canTalk = false;
                }
            }
        }
    }
}